#include "textureManager.h"
#include "stringFunctions.h"
#include <sstream>
textureManager* TM()
{
	return textureManager::instance();
}
textureManager::textureManager()
{
//... perform necessary instance initializations
}
textureManager* textureManager::pinstance = 0;// initialize pointer


void textureManager::clearTextures()
{
	glBindTexture(GL_TEXTURE_2D,0);
}

void textureManager::freeTexture(std::string id)
{
	std::vector<tex*>::iterator it;
	for(it = texture.begin(); it != texture.end(); it++)
	{
		if((*it)->id == id)
		{
			glDeleteTextures(1, &(*it)->texture);
			delete (*it);
			texture.erase(it);
			break;
		}
	}
}
bool textureManager::loadAnimationStrip(std::string path, int columns, int rows)
{
    std::string fileName = getFileName(path);
    std::string fileExt = getFileExt(fileName);
    if(fileExt.compare(".png") != 0 && fileExt.compare(".jpg") != 0 && fileExt.compare(".bmp") != 0)
        return false;
	ILuint texid;
	bool success;
	ilInit(); /* Initialization of DevIL */
	ilEnable(IL_ORIGIN_SET);
	ilGenImages(1, &texid); /* Generation of one image name */
	ilBindImage(texid); /* Binding of image name */

    std::string loadPath = path;

	success = ilLoadImage((char*)loadPath.c_str());
	success = ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
	int totalWidth = ilGetInteger(IL_IMAGE_WIDTH);
	int totalHeight = ilGetInteger(IL_IMAGE_HEIGHT);
	int cellWidth = totalWidth/columns;
	int cellHeight = totalHeight/rows;
	ILvoid* data;
	for(int x=0; x<totalWidth; x+=cellWidth)
	{
		for(int y=0; y<totalHeight; y+=cellHeight)
		{
			success = ilCopyPixels(x,y,0,cellWidth,cellHeight,1,IL_RGBA,IL_UNSIGNED_BYTE,data);
			ilSetData(data);
		}
	}

	tex* t = new tex;
	t->id = fileName;
	t->width = ilGetInteger(IL_IMAGE_WIDTH);
	t->height = ilGetInteger(IL_IMAGE_HEIGHT);


	std::cout << "Animation Strip loaded " << path << "\n";
	return true;
}

bool textureManager::loadTexture(std::string path)
{
    std::string fileName = getFileName(path);
    std::string fileExt = getFileExt(fileName);
    if(fileExt.compare(".png") != 0 && fileExt.compare(".jpg") != 0 && fileExt.compare(".bmp") != 0)
        return false;
	ILuint texid;
	bool success;
	ilInit(); /* Initialization of DevIL */
	ilEnable(IL_ORIGIN_SET);
	ilGenImages(1, &texid); /* Generation of one image name */
	ilBindImage(texid); /* Binding of image name */

    std::string loadPath = path;

	success = ilLoadImage((char*)loadPath.c_str());

	success = ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);


	tex* t = new tex;
	t->id = fileName;
	t->width = ilGetInteger(IL_IMAGE_WIDTH);
	t->height = ilGetInteger(IL_IMAGE_HEIGHT);

	glGenTextures(1,&t->texture);
    glBindTexture(GL_TEXTURE_2D,t->texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* We will use linear
      interpolation for magnification filter */
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); /* We will use linear
      interpolation for minifying filter */
	glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
      ilGetInteger(IL_IMAGE_HEIGHT), 0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE,
      ilGetData());

	ilDeleteImages(1, &texid);
	texture.push_back(t);

	std::cout << "Texture loaded " << path << "\n";
	return true;
}
bool textureManager::setTexture(std::string id)
{
	std::vector<tex*>::iterator it;
	for(it = texture.begin(); it != texture.end(); it++)
	{
		if((*it)->id == id)
		{
			glBindTexture(GL_TEXTURE_2D,(*it)->texture);
			return true;
		}
	}
	std::cout << "Error, could not find " << id << " was it loaded correctly?\n";
	return false;
}
GLuint textureManager::getTexture(std::string id)
{
	std::vector<tex*>::iterator it;
	for(it = texture.begin(); it != texture.end(); it++)
	{
		if((*it)->id == id)
		{
			return (*it)->texture;
		}
	}
	std::cout << "Error, could not find " << id << " was it loaded correctly?\n";
	return 0;
}

int textureManager::getTextureWidth(std::string id)
{
	std::vector<tex*>::iterator it;
	for(it = texture.begin(); it != texture.end(); it++)
	{
		if((*it)->id == id)
		{
			return (*it)->width;
		}
	}
}

int textureManager::getTextureHeight(std::string id)
{
	std::vector<tex*>::iterator it;
	for(it = texture.begin(); it != texture.end(); it++)
	{
		if((*it)->id == id)
		{
			return (*it)->height;
		}
	}
}

textureManager* textureManager::instance()
{
	if (!pinstance)
	{
		pinstance = new textureManager; // create sole instance
	}
	return pinstance; // address of sole instance
}

textureManager::~textureManager()
{
	std::vector<tex*>::iterator it;
	for(it = texture.begin(); it != texture.end(); it++)
	{
		glDeleteTextures(1, &(*it)->texture);
		delete (*it);
	}
}


using namespace boost::filesystem; //ALSO CHANGE TO READ LINE INSTEAD OF READ CHARACTER!!!
using namespace std;
void loadImageDirectory(const boost::filesystem::path & directory, bool recurse_into_subdirs)
{

	//std::cout << initial_path() << "\n";
    directory_iterator end;

    for( directory_iterator iter(directory) ; iter != end ; ++iter )
    {
        if ( is_directory( *iter ) )
        {
            //std::cout << iter->path() << " (directory)\n" ;
            if( recurse_into_subdirs ) loadImageDirectory(*iter, true) ;
        }
        std::stringstream s;
        s << iter->path();
        std::string out; s >> out;
        TM()->loadTexture(out);
    }
}
